#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)24   1.42   src/csm/core/cmds/lsnode.perl, csmcore, csm_rameh, rameh0431a 5/27/04 15:08:09

use strict;
use locale;
BEGIN
  {
	# this enables us to redirect where it looks for other CSM files during development
	$::csmroot = $ENV{'CSM_ROOT'} ? $ENV{'CSM_ROOT'} : '/opt/csm';
	$::csmpm = "$::csmroot/pm";
	$::csmbin = "$::csmroot/bin";
  }
use lib $::csmpm;
use Getopt::Std;
require NodeUtils;

# For the usage, see nodecmds.msg
sub usage { NodeUtils->message('I', 'IMsgLsnodeUsage');  exit (scalar(@_) ? $_[0] : 1); }

$::MSGCAT = 'nodecmds.cat';
$::MSGMAPPATH = "$::csmroot/msgmaps";
$::MSGSET = 'lsnode';     # setting this explicitly so it will work with the old dmsctrl link

# Parse the cmd line args and check them
if (! getopts('ispw:a:Ad:D:lxN:hvVf:SHFn:') ) { &usage; }
if ($::opt_h) { &usage(0); }
if (defined($::opt_w) && ((scalar(@ARGV)>0) || defined($::opt_f) || defined($::opt_N) || defined($::opt_n)) ) { &usage; }
if ((($::opt_i || $::opt_s) + $::opt_p + defined($::opt_a)) > 1) { &usage; }
if (($::opt_i + $::opt_s + $::opt_p + $::opt_A)>1 && !$::opt_l) { &usage; }
if (($::opt_i || $::opt_s) && $::opt_l) { &usage; }
if ((defined($::opt_a) + $::opt_A) > 1) { &usage; }
if ((defined($::opt_d) + defined($::opt_D) + $::opt_l) > 1) { &usage; }
if ($::opt_S && ($::opt_i || $::opt_s || $::opt_l)) { &usage; }

# Defaults
$::delim = $::opt_D || $::opt_d || ', ';     # delimiter within a row (resource)
$::linedelim = "\n";    # delimiter between rows (resources)
# make -A the default for -l
if ($::opt_l && (($::opt_i || $::opt_s) + $::opt_p + defined($::opt_a))==0) { $::opt_A = 1; }
if ($::opt_S) { $::opt_x = 1; }       # make -S imply -x
if ($::opt_F) { $::opt_l = 1; $::opt_A = 1; }
my $hostnameAttr = $::opt_H ? 'Name' : 'Hostname';
$::VERBOSE = $::opt_v || $::opt_V;

$ENV{'CT_MANAGEMENT_SCOPE'} = 1;   # set local scope so we can access IBM.ManagedNode and IBM.NodeGroup

my $select = &getSelect;

my %opthash;
if (defined($::opt_w))
  {
	if (!($::opt_w eq '*')) { $opthash{'WhereStr'} = $::opt_w; }
	# else, we don't specify a where string, so we get everything
  }
else							# get nodes from ARGV, -N, and -f
  {
	$NodeUtils::errno = 0;
	$::nodelist = NodeUtils->gatherNodeList(\@ARGV);
	#print "errno=$NodeUtils::errno\n";
	if ($NodeUtils::errno==31 || $NodeUtils::errno==32) { exit 12; }   # the node group was not found
	elsif ($NodeUtils::errno==30) { exit 13; }   # the node list file was not found
	if (!scalar(@$::nodelist))
	  {
		# If they tried to specify some nodes, but it resulted in an empty list, print nothing.
		# Otherwise, we continue on with an empty nodelist and display all nodes.
		if (scalar(@ARGV) || defined($::opt_n) || defined($::opt_N) || defined($::opt_f)) { exit; }
	  }
	#$::nodelist = NodeUtils->resolveAndUndup($::nodelist);
	#$opthash{'SkipResolve'} = 1;
  }

if ($::opt_l) { $opthash{'IncludeAttrNames'} = 1; }
if ($::opt_H)
  {
	$opthash{'ResourceClass'} = 'IBM.Host';
	$ENV{'CT_MANAGEMENT_SCOPE'} = 3;      # set scope to whole cluster
  }

my $outputref = NodeUtils->listNodeAttrs($::nodelist, $select, \%opthash);

@$outputref = sort @$outputref;

if ($::opt_l) { &longFormat($outputref); }
else { &shortFormat($outputref); }


exit;



# Form the select string - the attributes to be returned
sub getSelect
  {
	my $select;
	if ($::opt_A) { $select = ''; }
	elsif ($::opt_i || $::opt_s) { $select = $hostnameAttr; }
	elsif ($::opt_p) { $select = 'Status'; }
	elsif (length($::opt_a)) { $select = $::opt_a; }
	else { $select = $hostnameAttr; }

	# Modify the select str if we need to include a prefix
	if (!$::opt_l)
	  {
		$::prefix = 1;       # by default we prefix each line with the short hostname
		if ($::opt_x || $::linedelim ne "\n" || !length($select) || (($select=~/\b$hostnameAttr\b/) && !$::opt_i)) { $::prefix = 0; }
		if ($::prefix && !$::opt_i) { $select = "$hostnameAttr $select"; }
	  }
	return $select;
  }


sub longFormat
  {
	my ($outref) = @_;

	#my $numfound = scalar(@$outref);              # will check this after displaying what we did find
	
	# Process the returned rows of data
	my $firsttime = 1;
	my ($YES, $NO, $ON, $OFF, $UNKNOWN);
	foreach my $l (@$outref)
	  {
		if ($::opt_F) { print "\n"; }
		else
		  {
			if (!$firsttime) { print "-------------------\n"; }   # separate this resource from the previous
			else { $firsttime = 0; }
		  }

		# takes the alternating attrs and values and puts them in the hash correctly
		my %attrs = split(/:\|:/, $l);

		delete $attrs{"ActivePeerDomain"};

		# Make sure the hostname is displayed 1st
		if (defined($attrs{$hostnameAttr}))
			{
			  if ($::opt_F) { print "$attrs{$hostnameAttr}:\n"; }
			  else { print " $hostnameAttr = $attrs{$hostnameAttr}\n"; }
			  delete $attrs{$hostnameAttr};          # so we do not repeat it in the following loop
			}


		if ($::opt_F)
		  {
			# Remove the attributes that should not go into a nodedef file
			foreach my $a (qw(AllowManageRequest ConfigChanged ChangedAttributes CSMVersion LastCFMUpdateTime PowerStatus Status Name NodeNameList UniversalId UpdatenodeFailed InstallStatus ))
			  { delete $attrs{$a}; }
		  }
		else       # this is a regular -l output format
		  {
			# Give Nmemonic explanations for some of the attributes
			my $r;				# this reduces the # of hash lookups
			if (defined($r=$attrs{'AllowManageRequest'}))
			  {
				&getMeanings();
				if ($r == 0) { $attrs{'AllowManageRequest'} .= " $::NO"; }
				elsif ($r == 1) { $attrs{'AllowManageRequest'} .= " $::MGMT_REQUEST"; }
			  }
			if (defined($r=$attrs{'ConfigChanged'}))
			  {
				&getMeanings();
				$attrs{'ConfigChanged'} .= $r ? " $::YES" : " $::NO";
			  }
			if (defined($r=$attrs{'PowerStatus'}))
			  {
				&getMeanings();
				$attrs{'PowerStatus'} .= ($r ? ($r==1?" $::ON":($r==128?" $::UNCONFIGURED":" $::UNKNOWN")) : " $::OFF");
			  }
			if (defined($r=$attrs{'Status'}))
			  {
				&getMeanings();
				$attrs{'Status'} .= ($r ? ($r==1?" $::ALIVE":" $::UNKNOWN") : " $::UNREACHABLE");
			  }
			if (defined($r=$attrs{'UpdatenodeFailed'}))
			  {
				&getMeanings();
				$attrs{'UpdatenodeFailed'} .= $r ? " $::TRUE" : " $::FALSE";
			  }
		  }

		# Now display the rest of the attributes, sorted
		foreach my $k (sort keys %attrs)
		  {
			if ($::opt_F && !length($attrs{$k})) { next; }
			print " $k = $attrs{$k}\n";
		  }
	  }

	&checkForNotFound();
  }


# Gets a list of the words: (yes) (no) (on) (off) (unknown)
# and puts them in global vars
sub getMeanings
  {
	# Check if we already got them so we do not do it every time.
	if (!defined($::YES))
	  {
		($::YES, $::NO, $::ON, $::OFF, $::UNKNOWN, $::TRUE, $::FALSE, $::MGMT_REQUEST) = split(/\|/, NodeUtils->getMessage('IMsgATTRIBUTE_MEANINGS'));
		($::UNREACHABLE, $::ALIVE, $::UNCONFIGURED) = split(/\|/, NodeUtils->getMessage('IMsgStatusATTRIBUTE_MEANINGS'));
	    }
  }


sub shortFormat
  {
	my ($outref) = @_;
	
	#my $numfound = scalar(@$outref);              # will check this after displaying what we did find

	if ($::opt_S)
	  {
		my $ref2 = [];
		@$ref2 = sort @$outref;
		$outref = $ref2;
	  }

	my $firsttime = 1;
	my $prefstr = '';
	foreach my $l (@$outref)
	  {
		if (!$firsttime) { print $::linedelim; }   # separate this row from the previous
		else { $firsttime = 0; }
		my @row = split(/:\|:/, $l);
		
		#Note: With both -i and -s there is only 1 column.  Someday support -i and -s with -A.
		if ($::opt_s)        # display short hostname - strip domain from hostname
		  { ($row[0]) = split(/\./, $row[0]); }
		elsif ($::prefix)      # use the 1st column to form the prefix
		  {
                        if (NetworkUtils->isIpaddr($row[0])) 
                         { ($prefstr) = $row[0]; }  # do not strip 
                        else
                         { ($prefstr) = split(/\./, $row[0]); }  # strip domain from hostname
			$prefstr .= ':  ';
			if (!$::opt_i) { shift @row; }      # the hostname was just there for the prefix
		  }
		if ($::opt_i)             # change the hostname to ip address
		  {
			my ($hostname, $ipaddr) = NodeUtils->getHost($row[0]);
			$row[0] = $ipaddr;
		  }
		elsif($::opt_p){
			my $val = $row[0];
			&getMeanings();
			$row[0] .= ($val ? ($val==1?" $::ALIVE":" $::UNKNOWN") : " $::UNREACHABLE");
		}
			
		
		print $prefstr, join($::delim, @row);
	  }
	
	if (!$firsttime) { print "\n"; }    # end with a newline unless there was no output
	
	&checkForNotFound();
}


sub checkForNotFound
  {
	#my $numfound = shift;
	#if (defined(@$::nodelist) && scalar(@$::nodelist) && $numfound<scalar(@$::nodelist))
	if ($::LISTNODEATTRS_NUMNOTFOUND)
	  {
		if (scalar(@$::nodelist) == 1) { NodeUtils->message('E12', 'EMsgNODE_NOT_FOUND', $$::nodelist[0]); }
		elsif (scalar(@$::nodelist) <= 10) { NodeUtils->message('W12', 'EMsgSOME_NOT_FOUND_LIST', join(', ',@$::nodelist)); }
		else { NodeUtils->message('W12', 'EMsgSOME_NOT_FOUND'); }
	  }
  }
